import { track, trigger } from "../effect"
import { reactive, readonly } from "../reactive"
import { isPlainObject, isArray, isIntegerKey, hasOwn } from "../utils"
import { TrackOpType, TriggerOpType } from "../const"


function defineGetter(isReadonly:boolean=false, isShallow:boolean=false) {
  return function(target:any, p:string|symbol, receiver:any) {
    const value = Reflect.get(target, p, receiver)

    if(!isReadonly) track(target, TrackOpType.GET, p)
    if(!isShallow) {
      if(isPlainObject(value)) {
        return readonly ? readonly(value):reactive(value)
      }
    }

    return value
  }
}

function defineSetter(isReadonly:boolean=false, isShallow:boolean=false) {
  return function(target:object, p:string, newValue:any, receiver:any) {
    if(isReadonly) {
      console.warn('')
      return true
    }

    const oldValue = Reflect.get(target, p)

    const existKey = isArray(target) && isIntegerKey(p) 
      ? parseInt(p) < target.length
      : hasOwn(target, p)

    const result = Reflect.set(target, p, newValue, receiver)  

    if(existKey) {
      if(Object.is(newValue, oldValue)) return true
       
    } else {
    
    } 

    trigger(target, existKey ? TriggerOpType.SET : TriggerOpType.ADD, p)

    return result
  }
}

const get = defineGetter()
const shallowGet = defineGetter(false, true)
const readonlyGet = defineGetter(true, false)
const shallowReadonlyGet = defineGetter(true, true)

const set = defineSetter()
const shallowSet = defineSetter(false, true)
const readonlySet = defineSetter(true, false)
const shallowReadonlySet = defineSetter(true, true)


export const reactiveHandler: ProxyHandler<any> = {
  get,
  set,
  has(target, p) {
    return true  
  },
  defineProperty(target, property, attributes) {
    return true   
  },
  ownKeys(target) {
    return []  
  }
}

export const shallowReactiveHandler: ProxyHandler<any> = {}
export const readonlyHandler: ProxyHandler<any> = {}
export const shallowReadonlyHandler: ProxyHandler<any> = {}
